package com.jl;

import com.jl.config.JLGateWayRouteConfig;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.BooleanSpec;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 路由配置
 */
@Slf4j
@Configuration
@AllArgsConstructor
@ConditionalOnProperty(name = "jl.cloud.gateway.auto", havingValue = "false")
public class JLGateWayRoute {

    private JLGateWayRouteConfig jlGateWayRouteConfig;

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        RouteLocatorBuilder.Builder routes = builder.routes();
        if (jlGateWayRouteConfig.getRoute() != null) {
            String fallBackUrl = jlGateWayRouteConfig.getRoute().getFallBackUrl();
            fallBackUrl = StringUtils.isEmpty(fallBackUrl) ? "/defaultFallBack" : fallBackUrl;
            List<JLGateWayRouteConfig.Route.RouteParam> list = jlGateWayRouteConfig.getRoute().getList();
            if (list != null) {
                for (JLGateWayRouteConfig.Route.RouteParam route : list) {
                    String path = route.getPath();
                    path = path.indexOf("/") == 0 ? path.substring(1) : path;
                    path = path.lastIndexOf("/") == path.length() - 1 ? path.substring(0, path.length() - 1) : path;
                    String finalPath = path;

                    String routeFallBackUrl = route.getFallBackUrl();
                    routeFallBackUrl = StringUtils.isEmpty(routeFallBackUrl) ? fallBackUrl : routeFallBackUrl;
                    routeFallBackUrl = !routeFallBackUrl.substring(0, 1).equals("/") ? "/" + routeFallBackUrl : routeFallBackUrl;
                    String finalFallBackUrl = routeFallBackUrl;
                    routes.route(p -> {
                        BooleanSpec booleanSpec = p.path(String.format("/%s/**", finalPath));
                        if (route.getType() != null) {
                            booleanSpec.and().method(route.getType().toUpperCase().split(","));
                        }
                        return booleanSpec.filters(f -> f
                                .rewritePath(String.format("/%s/(?<segment>.*)", finalPath), "/${segment}")
                                .hystrix(config -> config
                                        .setName(route.getServiceName())
                                        .setFallbackUri("forward:" + finalFallBackUrl)
                                ))
                                .uri("lb://" + route.getServiceName());
                    });
                    log.info("gateway route：{} ----> {} ----> {}", route.getPath(), route.getType() == null ? "ALL" : route.getType().toUpperCase(), route.getServiceName());
                }
            }
        }
        return routes.build();
    }

    @RestController
    public static class JLFallback {

        @Value("${hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds}")
        private Integer timeout;

        /**
         * 默认降级方法
         *
         * @return
         */
        @GetMapping("defaultFallBack")
        public String defaultFallBack() {
            return String.format("服务降级，默认最大超时：%d(ms)", timeout);
        }

    }

}
